package cn.com.startai.huadiantrainer.global.speak;

import android.app.Application;
import android.media.AudioManager;

import com.baidu.tts.auth.AuthInfo;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.TtsMode;

import java.io.IOException;

import cn.com.startai.common.utils.CThreadPoolUtils;
import cn.com.startai.common.utils.TAndL;

/**
 * Created by Robin on 2019/6/3.
 * 419109715@qq.com 彬影
 */
public class SpeakManager {

    protected String appId = "16426909";

    protected String appKey = "bCDn3lYijWfiO63NzS22mYF0";

    protected String secretKey = "QevIWf033tS3AwzreKAQiOeVMqKW2yD1";

    // TtsMode.MIX; 离在线融合，在线优先； TtsMode.ONLINE 纯在线； 没有纯离线
    private TtsMode ttsMode = TtsMode.MIX;

    // ================选择TtsMode.ONLINE  不需要设置以下参数; 选择TtsMode.MIX 需要设置下面2个离线资源文件的路径
    private static final String TEMP_DIR = "/sdcard/baiduTTS"; // 重要！请手动将assets目录下的3个dat 文件复制到该目录

    // 请确保该PATH下有这个文件
    private static final String TEXT_FILENAME = TEMP_DIR + "/" + "bd_etts_text.dat";

    // 请确保该PATH下有这个文件 f7 是女声
    private static final String MODEL_FILENAME = TEMP_DIR + "/" + "bd_etts_common_speech_f7_mand_eng_high_am-mix_v3.0.0_20170512.dat";

    protected String offlineVoice = OfflineResource.VOICE_FEMALE;

    protected SpeechSynthesizer mSpeechSynthesizer;
    private Application application;

    private SpeakManager() {
    }

    public static SpeakManager getInstance() {
        return SingleTonHoulder.singleTonInstance;
    }


    private static class SingleTonHoulder {
        private static final SpeakManager singleTonInstance = new SpeakManager();
    }


    /**
     * 初始化
     */
    public void init(Application app) {

        this.application = app;
        CThreadPoolUtils.getInstance().getWorkThreadPool().execute(new Runnable() {
            @Override
            public void run() {

                boolean isMix = ttsMode.equals(TtsMode.MIX);
                boolean isSuccess;
                // 1. 获取实例
                mSpeechSynthesizer = SpeechSynthesizer.getInstance();
                mSpeechSynthesizer.setContext(application);

                // 2. 设置listener
                mSpeechSynthesizer.setSpeechSynthesizerListener(new MessageListener());

                // 3. 设置appId，appKey.secretKey
                int result = mSpeechSynthesizer.setAppId(appId);
                checkResult(result, "setAppId");
                result = mSpeechSynthesizer.setApiKey(appKey, secretKey);
                checkResult(result, "setApiKey");

                // 4. 支持离线的话，需要设置离线模型
                if (ttsMode == TtsMode.MIX) {
                    // 检查离线授权文件是否下载成功，离线授权文件联网时SDK自动下载管理，有效期3年，3年后的最后一个月自动更新。
                    isSuccess = checkAuth();
                    if (!isSuccess) {
                        return;
                    }
                    OfflineResource offlineResource = createOfflineResource(offlineVoice);
                    // 文本模型文件路径 (离线引擎使用)， 注意TEXT_FILENAME必须存在并且可读
                    mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, offlineResource.getTextFilename());
                    // 声学模型文件路径 (离线引擎使用)， 注意TEXT_FILENAME必须存在并且可读
                    mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, offlineResource.getModelFilename());
                }

                // 5. 以下setParam 参数选填。不填写则默认值生效
                // 设置在线发声音人： 0 普通女声（默认） 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
                mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
                // 设置合成的音量，0-9 ，默认 5
                mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "9");
                // 设置合成的语速，0-9 ，默认 5
                mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");
                // 设置合成的语调，0-9 ，默认 5
                mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");

                mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_HIGH_SPEED_SYNTHESIZE);
                // 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
                // MIX_MODE_DEFAULT 默认 ，wifi状态下使用在线，非wifi离线。在线状态下，请求超时6s自动转离线
                // MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI wifi状态下使用在线，非wifi离线。在线状态下， 请求超时1.2s自动转离线
                // MIX_MODE_HIGH_SPEED_NETWORK ， 3G 4G wifi状态下使用在线，其它状态离线。在线状态下，请求超时6s自动转离线
                // MIX_MODE_HIGH_SPEED_SYNTHESIZE, 2G 3G 4G wifi状态下使用在线，其它状态离线。在线状态下，请求超时1.2s自动转离线

                mSpeechSynthesizer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                // x. 额外 ： 自动so文件是否复制正确及上面设置的参数
//        Map<String, String> params = new HashMap<>();
                // 复制下上面的 mSpeechSynthesizer.setParam参数
                // 上线时请删除AutoCheck的调用
//        if (isMix) {
//            params.put(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, TEXT_FILENAME);
//            params.put(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, MODEL_FILENAME);
//        }
//
//        InitConfig initConfig = new InitConfig(appId, appKey, secretKey, ttsMode, params, null);
//        AutoCheck autoCheck = AutoCheck.getInstance(app).innerCheck(initConfig);
//        String message = autoCheck.obtainDebugMessage();
//        TAndL.L(message);

                // 6. 初始化
                result = mSpeechSynthesizer.initTts(ttsMode);
                checkResult(result, "initTts");
            }
        });
    }


    /**
     * 释放资源
     */
    public void release() {
        if (mSpeechSynthesizer != null) {
            mSpeechSynthesizer.stop();
            mSpeechSynthesizer.release();
            mSpeechSynthesizer = null;
            TAndL.L("speak 释放资源成功");
        }
    }

    public void speak(String text) {
        /* 以下参数每次合成时都可以修改
         *  mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
         *  设置在线发声音人： 0 普通女声（默认） 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
         *  mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "5"); 设置合成的音量，0-9 ，默认 5
         *  mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5"); 设置合成的语速，0-9 ，默认 5
         *  mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5"); 设置合成的语调，0-9 ，默认 5
         *
         *  mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
         *  MIX_MODE_DEFAULT 默认 ，wifi状态下使用在线，非wifi离线。在线状态下，请求超时6s自动转离线
         *  MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI wifi状态下使用在线，非wifi离线。在线状态下， 请求超时1.2s自动转离线
         *  MIX_MODE_HIGH_SPEED_NETWORK ， 3G 4G wifi状态下使用在线，其它状态离线。在线状态下，请求超时1.2s自动转离线
         *  MIX_MODE_HIGH_SPEED_SYNTHESIZE, 2G 3G 4G wifi状态下使用在线，其它状态离线。在线状态下，请求超时1.2s自动转离线
         */

        if (mSpeechSynthesizer == null) {
            TAndL.L("[ERROR], speak 初始化失败");
            return;
        }
        int result = mSpeechSynthesizer.speak(text);
        TAndL.L("speak 合成并播放 ");
        checkResult(result, "speak");
    }

    private void stop() {
        TAndL.L("speak 停止合成引擎");
        int result = mSpeechSynthesizer.stop();
        checkResult(result, "stop");
    }


    private void checkResult(int result, String method) {
        if (result != 0) {
            TAndL.L("speak error code :" + result + " method:" + method + ", 错误码文档:http://yuyin.baidu.com/docs/tts/122 ");
        }
    }

    /**
     * 检查appId ak sk 是否填写正确，另外检查官网应用内设置的包名是否与运行时的包名一致。本demo的包名定义在build.gradle文件中
     *
     * @return
     */
    private boolean checkAuth() {
        AuthInfo authInfo = mSpeechSynthesizer.auth(ttsMode);
        if (!authInfo.isSuccess()) {
            // 离线授权需要网站上的应用填写包名。本demo的包名是com.baidu.tts.sample，定义在build.gradle中
            String errorMsg = authInfo.getTtsError().getDetailMessage();
            TAndL.L("speak 【error】鉴权失败 errorMsg=" + errorMsg);
            return false;
        } else {
            TAndL.L("speak 验证通过，离线正式授权文件存在。");
            return true;
        }
    }

    protected OfflineResource createOfflineResource(String voiceType) {
        OfflineResource offlineResource = null;
        try {
            offlineResource = new OfflineResource(application, voiceType);
        } catch (IOException e) {
            // IO 错误自行处理
            e.printStackTrace();
            TAndL.L("speak 【error】:copy files from assets failed." + e.getMessage());
        }
        return offlineResource;
    }

}
